#pragma once

#include <math/math.hpp>
#include <boost/noncopyable.hpp>
#include <boostext/signal.hpp>
#include <engine.core/math.hpp>

#include "win_exports.hpp"




namespace WinUi
{
	class WINUI_API Widget
		: public boost::noncopyable
	{
	public:

		friend class Dialog;

		/// Defines a simple notification signal
		typedef boost::signals2::signal<void()>   notification;

	protected:

		struct                impl;
		std::auto_ptr<impl>   d;

	private:

		/// Defines the position of the window in screen space
		int2   m_pos;

		/// Defines the size of the window in pixels (width/height)
		int2   m_size;

		/// Defines the size of the window interior, ie the size that is usable
		int2   m_clientSize;

	protected:

		/// Emitted when the window has been painted
		notification   m_destroyed;

	public:

		boostext::connector<notification>   destroyed;

	public:

		/**
		 * Create a widget.
		 *
		 * @param parent        the parent of the widget
		 * @param className     the name of the window class, that will be registered with windows
		 * @param pos           the position of the widget, relative to the upper left corner of the parent
		 * @param size          the size of the widget, in pixels
		 * @param [opt] style   the style for the widget
		 */
		Widget(Widget* parent, const std::wstring& className, int2 pos, int2 size, int style = 0);
		virtual ~Widget();



		/**
		 * Get the parent of this widget.
		 */
		Widget* parent() const;

		/**
		 * Set the parent of this widget.
		 */
		void setParent(Widget *parent);



		/**
		 * Get the position of the widget in screen space.
		 */
		int2 pos() const;

		/**
		 * Get the size of the widget.
		 */
		int2 size() const;

		/**
		 * Get the client size of the widget.
		 * This excludes the frame, titlebar, etc... and only
		 * returns the usable size of the widget.
		 */
		int2 clientSize() const;



		/**
		 * Set the text of the widget.
		 */
		void setText(const std::wstring& name);

		/**
		 * Set the position of the widget in parent space.
		 */
		void setPos(int2 pos);
		void setPos(int x, int y);

		/**
		 * Set the size of the widget.
		 */
		void setSize(int2 size);
		void setSize(int width, int height);



		/**
		 * Show this widget.
		 */
		void show();

		/**
		 * Hide this widget.
		 */
		void hide();



		/**
		 * Test if this widget is enabled.
		 *
		 * @return true when the widget is enabled, otherwise false
		 */
		bool enabled() const;

		/**
		 * Test if this widget is disabled.
		 *
		 * @return true when the widget is disabled, otherwise false
		 */
		bool disabled() const;

		/**
		 * Enable this widget.
		 *
		 * @param b   flag that tells if the widget shall be enabled or disabled (true: enabled)
		 */
		void enable(bool b = true);

		/**
		 * Disable this widget.
		 *
		 * @param b  flag that tells if the widget shall be disabled or enabled (true: disabled)
		 */
		void disable(bool b = true);



		/**
		 * Test if this widget is visible.
		 */
		bool visible() const;

	protected:

		virtual LRESULT msgProc(UINT msg, WPARAM wParam, LPARAM lParam);

	private:

		void updateClientSize();
	};
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
